home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac 1993 September / September 93.iso / Archives / Fun, Tricks & Hacks / New Aquarium / Aquarium3.pas next >
Pascal/Delphi Source File  |  1988-04-24  |  19KB  |  648 lines

  1. {       APRIL 23, 10PM - Latest version
  2.         V2.0 (when menus work - for now, V1.9) (They work! They work!)
  3.  
  4.  This is an attempt to duplicate the program 'Aquarium,' which takes up a
  5.     whopping 35K of disk space. My guess is that it could be done in less room.
  6.     Also, a good chance to learn about PICT resources & CopyBits calls.
  7.     The general gist is thus: 1) Open the ScrapBook file (or whichever one
  8.     has the fish PICT in it); 2) Open a window over the entire screen;
  9.     3) Move the fish around, bouncing it off of the window edges;
  10.     4) Exit when the user presses a key or clicks the mouse button.
  11.  
  12.     Updates: Aquarium1 used 'BlockMove' to copy the fish in from an offscreen
  13.         BitMap which was redrawn at every iteration, rather than draw
  14.         it directly on the screen; Aquarium2 uses 4 offscreen bitmaps-
  15.         instead of redrawing the offscreen bitmap and BlockMoving it, 2
  16.         simply decides which fish to copy to the screen and does it.
  17.         It is therefore about 8 times faster.
  18.         The current version uses a LOT of new code for menus & general
  19.         event handling.}
  20.  
  21. PROGRAM Aquarium2;
  22.  
  23. {$U-}               {Turn normal Unit usage off}
  24. {$R-}               {Range checking off =$R-}
  25. {$D+}               {Generate Debug symbols}
  26. {$I+}               {Check I/O results}
  27. {$B+}               {Set the Finder Bundle bit}
  28. {$T APPLAqrm}       {Type & creator}
  29. (*{$O DS Turbo's:Aquarium2.0 }*)    {Output file directory:name}
  30.  
  31. uses MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf;
  32.  
  33. CONST
  34. Chicago     = SystemFont;
  35. AppleID     = 128;
  36. FileID      = 129;
  37. EditID      = 130;
  38. QuitItem    = 1;
  39.  
  40. VAR {Globals}
  41. indx,
  42. MaxWidth,
  43. MaxHeight,
  44. MinWidth,
  45. MinHeight,
  46. hdist,
  47. vdist:          integer;
  48. myDelay,
  49. myTicks:        longInt;
  50. FishRect,
  51. bounds:         rect;       {for setting up the screen}
  52. WhichFish,
  53. visible:        boolean;
  54. theWindP:       WindowPtr;
  55. anevent:        eventRecord;
  56. myPort:         grafPtr;
  57. ProgramDone:    boolean;
  58. PicHandle1,
  59. PicHandle2,
  60. PicHandle3,
  61. PicHandle4:     PicHandle;
  62. TempBits:       array[1..4] of BitMap;
  63. AppleMenu,
  64. FileMenu,
  65. EditMenu:       MenuHandle;
  66. where:          point;
  67.  
  68.  
  69.  
  70. {------------------- Whew! Now, on to the good stuff -------------------}
  71.  
  72.  
  73.  
  74. PROCEDURE debugger; inline $A9FF;   {crash into the debugger, not bomb box}
  75.  
  76.  
  77.  
  78. PROCEDURE crash;
  79. BEGIN
  80.     debugger;
  81. END;
  82.  
  83.  
  84.  
  85. PROCEDURE Debug( Astr1, Astr2: str255);
  86. VAR
  87.     r:              rect;
  88.     WindP:          WindowPtr;
  89.     CurPort:        GrafPtr;
  90.     b:              boolean;
  91.     bEvent:         EventRecord;
  92. BEGIN
  93.     GetPort(CurPort);
  94.     SetPort(MyPort);
  95.     WITH thePort^.portBits.bounds DO
  96.         SetRect( r, Left + 100, Top + 100, Right - 100, Bottom - 100);
  97.     WindP := NewWindow( nil, r, '', visible, DBoxProc,
  98.                                             Pointer(-1), True, 0);
  99.     MoveTo (150, 150);
  100.     TextFont(Chicago);
  101.     TextSize(12);
  102.     DrawString(Astr1);     {Probably Shouldn't use fixed coordinates}
  103.     MoveTo (150, 180);         
  104.     DrawString(Astr2);
  105.     REPEAT
  106.         b := GetNextEvent(KeyDownMask + MDownMask, bEvent);
  107.     UNTIL b;
  108.     DisposeWindow(WindP);
  109.     SetPort(CurPort);
  110. END;
  111.  
  112.  
  113. PROCEDURE SetUpScreen;
  114. VAR
  115.     a:      boolean; 
  116. BEGIN
  117.     New(MyPort);                {get a GrafPtr}
  118.     if MemError <> noErr then
  119.     BEGIN
  120.         SysBeep(1);
  121.         debug('Out of RAM', '');
  122.         repeat
  123.             a := GetNextEvent( keyDownMask + mDownMask, anEvent);
  124.             SystemTask;
  125.         until a;
  126.         ExitToShell;
  127.     END;
  128.     OpenPort(MyPort);
  129.     bounds:= MyPort^.portBits.bounds;   {full screen size}
  130.     bounds.top := bounds.top + 20;
  131.     theWindP:= NewWindow( nil, bounds, '', visible, plainDBox,
  132.                                             Pointer(-1), True, 0);
  133.     if MemError <> noErr then
  134.     BEGIN
  135.         SysBeep(1);
  136.         debug('Out of window RAM', '');
  137.         repeat
  138.             a := GetNextEvent( keyDownMask + mDownMask, anEvent);
  139.             SystemTask;
  140.         until a;
  141.         ExitToShell;
  142.     END;
  143.  
  144.     FillRect(bounds, white);
  145. { for inverted fish: do 
  146.     FillRect(bounds, black);  and see SetUpBitMaps}
  147. end;
  148.  
  149. { ---------------------------------- end SetUpScreen --------------- }
  150.  
  151.  
  152.  
  153. procedure Init;
  154. BEGIN           {--------general initializing}
  155.     MoreMasters;
  156.     InitGraf(@thePort);
  157.     Randseed := TickCount;
  158.     InitFonts;
  159.     FlushEvents(Everyevent, 0);
  160.     InitWindows;
  161.     InitMenus;
  162.     TEInit;
  163.     InitDialogs(@crash);
  164.     InitCursor;
  165.     PenNormal;
  166.    {-------------------- program specific inits}
  167.     myTicks := 0;
  168.     visible:= true;
  169.     SetUpScreen;        {get the port}
  170.     MaxWidth := MyPort^.portrect.right;
  171.     MaxHeight := MyPort^.portrect.bottom;
  172.     MinWidth := MyPort^.portrect.left;
  173.     MinHeight := MyPort^.portrect.top;
  174.     programDone := false;
  175.     TextFont(Geneva);
  176.     TextSize(9);
  177.     WhichFish := true;
  178. end;
  179.  
  180.  
  181.  
  182. procedure ResFork;
  183. VAR
  184.     a:              boolean;
  185.     TheError,
  186.     TheRefNum:      integer;
  187.     anEvent:        EventRecord;
  188.     TheFileName:    String[63];
  189. BEGIN
  190.     TheError := noErr;
  191.     a := false;
  192. (*  theRefNum := OpenResFile( 'DS Turbo''s:XAquarium');*) {compile to RAM only}
  193.     theRefNum := CurResFile;        {compile to disk ONLY}
  194.                                     {get our appl rsrc file ref# to use}
  195.     TheError:= ResError;
  196.     If TheError <> noErr then
  197.     BEGIN
  198.         Debug('Resource file not found', '');
  199.         ExitToShell;
  200.     END {if};
  201. END;
  202.  
  203.  
  204.  
  205. PROCEDURE GetPic;
  206. BEGIN
  207.     PicHandle1 := GetPicture( -32760);     {rh, reg}
  208.     PicHandle2 := GetPicture( -32762);     {rh, up}
  209.     PicHandle3 := GetPicture( -32763);     {lh, reg}
  210.     PicHandle4 := GetPicture( -32761);     {lh, up}
  211.     if PicHandle1 = NIL then
  212.     BEGIN
  213.         Debug('PicHandle 1 bad', '');
  214.         ExitToShell;
  215.     END;
  216.     if PicHandle2 = NIL then
  217.     BEGIN
  218.         Debug('PicHandle 2 bad', '');
  219.         ExitToShell;
  220.     END;
  221.     if PicHandle3 = NIL then
  222.     BEGIN
  223.         Debug('PicHandle 3 bad', '');
  224.         ExitToShell;
  225.     END;
  226.     if PicHandle4 = NIL then
  227.     BEGIN
  228.         Debug('PicHandle 4 bad', '');
  229.         ExitToShell;
  230.     END;
  231. END;    {GetPic}
  232.  
  233.  
  234.  
  235. PROCEDURE GetMenus;
  236. VAR
  237.     a:          boolean;
  238.     theError:   integer;
  239. BEGIN
  240.     theError := noErr;
  241.     a := false;
  242.     AppleMenu := GetMenu(128);
  243.     FileMenu := GetMenu(129);
  244.     EditMenu := GetMenu(130);
  245.     theError := ResError;
  246.     if theError <> noErr then
  247.     BEGIN
  248.         Debug('The Menus were not found', '');
  249.         ExitToShell;
  250.     END {if};
  251.  
  252.     AddResMenu( AppleMenu, 'DRVR');     {add the DAs}
  253.     InsertMenu(AppleMenu, 0);
  254.     InsertMenu(FileMenu, 0);
  255.     InsertMenu(EditMenu, 0);
  256.     DrawMenuBar;
  257. END;
  258.  
  259.  
  260.  
  261. FUNCTION SetHDist: integer;
  262. VAR
  263.     newx:   integer;
  264. BEGIN
  265.     newx:= abs(random) mod 9;           {was mod 9 * 2}
  266.     if newx = 0 then newx:= newx + 2;
  267.     SetHDist:= newx;
  268. END;
  269.  
  270.  
  271.  
  272. FUNCTION SetVDist: integer;
  273. VAR
  274.     newx:   integer;
  275. BEGIN
  276.     newx:= abs(random) mod 3;           {was mod 5}
  277.     if newx = 0 then newx:= newx + 2;
  278.     SetVDist:= newx;
  279.     myDelay := trunc( random mod 20 / 3);     {ticks}
  280. END;
  281.  
  282.  
  283.  
  284. PROCEDURE TestEdges;
  285. BEGIN
  286.         If FishRect.left >= MaxWidth - 30 then
  287.         BEGIN
  288.             hdist:= -SetHDist; {neg}
  289.             if FrontWindow = theWindP then DisableItem(EditMenu, 0);
  290.             DrawMenuBar;    {to show the now disabled Edit menu}
  291.         END;
  292.  
  293.         If FishRect.bottom >= MaxHeight - 1 then
  294.         BEGIN
  295.             vdist:= -SetVDist; {neg}
  296.             if FrontWindow = theWindP then DisableItem(EditMenu, 0);
  297.             DrawMenuBar;
  298.         END;
  299.  
  300.         If FishRect.right <= MinWidth + 30 then
  301.         BEGIN
  302.             hdist:= SetHDist; {pos}
  303.             if FrontWindow = theWindP then DisableItem(EditMenu, 0);
  304.             DrawMenuBar;
  305.         END;
  306.  
  307.         If FishRect.top <= MinHeight + 21 then
  308.         BEGIN
  309.             vdist:= SetVDist;   {pos}
  310.             if FrontWindow = theWindP then DisableItem(EditMenu, 0);
  311.             DrawMenuBar;
  312.         END;
  313. END;            {TestEdges}
  314.  
  315.  
  316.  
  317. PROCEDURE SetUpBitMaps;
  318. VAR
  319.     currentPort:        GrafPtr;
  320.     tempBMap:           BitMap;
  321.     theSize:            size;   {of BitMap}
  322.     indx:               integer;
  323.     str1:               str255;
  324.     a:                  boolean;
  325. BEGIN
  326.     { Note: we don't actually DRAW every time, we just COPY(bits) the
  327.         correct pict onscreen.
  328.         A- Set 4 rects to FishRect;
  329.         B- Setup array of 4 offscreen bitmaps using FishRect as bounds;
  330.         C- Draw the 4 fish into our 4 offscreen bitmaps;
  331.         C- Use IF stmt to choose 1 of 4 bitmaps- i.e., "then theFish# := 1;"
  332.         E- Use a single copy-to-screen statement:
  333.              CopyBits(TempBits[theFish], tempBMap, TempBits[theFish].bounds,
  334.                                             FishRect, srcCopy, nil);     }
  335.  
  336.     GetPort(currentPort);
  337.     tempBMap := currentPort^.portbits;
  338.     theSize := 38 * 164;        {=rowBytes * length}
  339.           { (Trunc((FishRect.right - FishRect.left) / 8) + 1) *
  340.                                 (FishRect.bottom - FishRect.top);  }
  341.     for indx := 1 to 4 do
  342.     BEGIN
  343.         TempBits[indx].baseAddr := NewPtr(theSize);
  344.         if MemError <> noErr then
  345.         BEGIN
  346.             SysBeep(1);
  347.             debug('Out of RAM, SetUpBitMaps', '');
  348.             repeat
  349.                 a := GetNextEvent( keyDownMask + mDownMask, anEvent);
  350.                 SystemTask;
  351.             until a;
  352.             ExitToShell;
  353.         END;
  354.  
  355.         TempBits[indx].rowBytes := 38;
  356.                             {Trunc((FishRect.right-FishRect.left) / 8) + 1}
  357.         TempBits[indx].bounds := FishRect;
  358.     END;
  359.  
  360.     SetPortBits(TempBits[1]);
  361.     DrawPicture( PicHandle1, TempBits[1].bounds);     {rh reg}
  362.     SetPortBits(TempBits[2]);
  363.     DrawPicture( PicHandle2, TempBits[2].bounds);     {rh uptail}
  364.     SetPortBits(TempBits[3]);
  365.     DrawPicture( PicHandle3, TempBits[3].bounds);     {lh reg}
  366.     SetPortBits(TempBits[4]);
  367.     DrawPicture( PicHandle4, TempBits[4].bounds);     {lh uptail}
  368.  
  369. {Note: for inverted fish, do the following ---
  370.     for indx := 1 to 4 do
  371.     BEGIN
  372.         SetPortBits(TempBits[indx]);
  373.         InvertRect(TempBits[indx].bounds);
  374.     END;
  375.         ---and also see SetUpScreen to paint whole screen black, not white.}
  376.  
  377.     SetPortBits(tempBMap);
  378. END; {SetUpBitMaps}
  379.  
  380.  
  381.  
  382. PROCEDURE DrawTheFish( VAR FishRect: rect);
  383. VAR
  384.     OldBits:        BitMap;
  385.     theTempBits:    BitMap;
  386.     currPort:       GrafPtr;
  387.     aSize:          size;
  388.     TitlePoint,
  389.     TitlePoint1:    point;
  390.     theFish:        integer;
  391. BEGIN
  392.     {By the way, we don't have to 'undraw' the fish, because the white
  393.         edge of the fish PICTure will always act as an eraser for the
  394.         previous time. This is true as long as we don't move the fish
  395.         a distance farther than the thickness of the border, about 30 pixels.}
  396.  
  397.     IF FrontWindow <> theWindP then
  398.         exit
  399.  
  400.    {*******IMPORTANT: some other window is in front of ours; therefore we
  401.     don't want to draw. If they obliterate part of our drawing, we just
  402.     fix it up after they go away.}
  403.  
  404.     ELSE
  405.         SetPort(MyPort);  {make sure it's our port}
  406.  
  407.     oldBits := MyPort^.portbits;    {set oldBits to original BitMap}
  408.     aSize := 38 * 164;              {rowBytes * length}
  409.  
  410.                      { ------- DRAW HERE -------- }
  411.     OffSetRect(Fishrect, hDist, vDist);     {move the actual rect coords}
  412.     IF WhichFish then
  413.         if hdist > 0 then       {right-going fish}
  414.             theFish := 1        {rh reg}
  415.         else                    {left-going fish}
  416.             theFish := 3        {lh reg}
  417.     ELSE
  418.         if hdist > 0 then
  419.             theFish := 2        {rh up}
  420.         else
  421.             theFish := 4;       {lh up}
  422.     WhichFish := NOT WhichFish;             {flip the fish: reg/uptail}
  423.  
  424.         {copy off-screen bitmap to on screen}
  425.     CopyBits(TempBits[theFish], oldBits, TempBits[theFish].bounds,
  426.                                                 FishRect, SrcCopy, nil);
  427. {Note: if the CopyBits destRect is not EXACTLY the same size as the SourceRect,
  428.         you will see speed degradation & possibly image distortion.}
  429.  
  430.     MoveTo(225, 14);                    {drawing into screenBits}
  431.     TextFont(Chicago);
  432.     TextSize(12);
  433.     DrawString('Aquarium');
  434.     MoveTo(bounds.left, bounds.top - 1);
  435.     LineTo(bounds.right, bounds.top - 1);
  436.     SetPortBits(oldBits);
  437. END;
  438.  
  439.  
  440.  
  441. PROCEDURE DoAbout;
  442. VAR
  443.     WindP:      WindowPtr;
  444.     SnailRect,
  445.     Wbounds:    rect;
  446.     b:          boolean;
  447.     bEvent:     EventRecord;
  448.     CurPort:    GrafPtr;
  449.     SnailPict:  PicHandle;
  450.     VersStr,
  451.     DateStr:    StringHandle;
  452. BEGIN
  453.     GetPort(CurPort);   {this fixed a nasty crashing problem w/MiniWriter DA}
  454.     SetPort(MyPort);
  455.     WITH thePort^.portBits.bounds DO
  456.         SetRect( Wbounds, Left + 100, Top + 100, Right - 100, Bottom - 100);
  457.     WindP := NewWindow( nil, Wbounds, '', visible, DBoxProc,
  458.                                             Pointer(-1), True, 0);
  459.     MoveTo (150, 150);
  460.     TextFont(Chicago);
  461.     TextSize(12);
  462.     DrawString('Aquarium');     {Probably Shouldn't use fixed coordinates}
  463.     MoveTo (150, 170);
  464.     VersStr := GetString( 128);    {version STR rsrc}
  465.     DrawString(VersStr^^);
  466.     MoveTo (150, 190);
  467.     DateStr := GetString( 129);    {Date STR rsrc}
  468.     DrawString(DateStr^^);
  469.     SnailPict := GetPicture(-32758);
  470.     if ResError <> noErr then
  471.     BEGIN
  472.         DisposeWindow(WindP);
  473.         exit;
  474.     END;
  475.     SetRect(SnailRect, 300, 153, 395, 199);
  476.     {right side, bottom of top text line}
  477.     DrawPicture(SnailPict, SnailRect);
  478.     REPEAT
  479.         b := GetNextEvent(KeyDownMask + MDownMask, bEvent);
  480.     UNTIL b;
  481.     DisposeWindow(WindP);
  482.     SetPort(CurPort);
  483. END;
  484.  
  485.  
  486.  
  487. PROCEDURE DoMouseDown;
  488. VAR
  489.     WhichWindow:    WindowPtr;
  490.     thePart:        integer;
  491.     dragRect:       rect;
  492.  
  493.  
  494.     PROCEDURE DoMenuClick;
  495.     VAR
  496.         MenuChoice:     longint;
  497.         temp,
  498.         theMenu,
  499.         theItem:        integer;
  500.         tempStr:        Str255;
  501.  
  502.  
  503.     BEGIN   {DoMenuClick}
  504.         MenuChoice := MenuSelect( anEvent.where);
  505.         if MenuChoice <> 0 then
  506.         BEGIN
  507.             theMenu := HiWord(MenuChoice);
  508.             theItem := LoWord(MenuChoice);
  509.             CASE theMenu OF
  510.                 AppleID:    IF theItem = 1 then
  511.                                 BEGIN
  512.                                     doAbout;
  513.                                 END
  514.                             ELSE
  515.                                 BEGIN
  516.                                     EnableItem(EditMenu, 0);
  517.                                     EnableItem(EditMenu, 1);
  518.                                     EnableItem(EditMenu, 3);
  519.                                     EnableItem(EditMenu, 4);
  520.                                     EnableItem(EditMenu, 5);
  521.                                     EnableItem(EditMenu, 6);
  522.                                     DrawMenuBar;
  523.                                     GetItem(AppleMenu, theItem, tempStr);
  524.                                     temp := OpenDeskAcc(tempStr);
  525.                                 END;
  526.                 FileID:     IF theItem = QuitItem then
  527.                                             ProgramDone := true;
  528.                 EditID:     if SystemEdit(theItem - 1) then; {nothing- our
  529.                                                      app doesn't use Edit menu}
  530.             END;    {case}
  531.  
  532.             HiliteMenu(0);
  533.         END;    {if MenuChoice...}
  534.     END;        {DoMenuClick}
  535.  
  536.  
  537. BEGIN   {DoMouseDown}
  538.     thePart := FindWindow(anEvent.where, whichWindow);
  539.     CASE thePart OF
  540.         InDesk:         {do nothing};
  541.         InMenuBar:      DoMenuClick;
  542.         InSysWindow:    SystemClick(anEvent, whichWindow);
  543.         InContent:      if whichWindow <> FrontWindow then
  544.                             SelectWindow(whichWindow);
  545.         InDrag:         {do nothing};
  546.         InGrow:         {do nothing};
  547.         InGoAway:       {don't have one};
  548.     END;    {case}
  549. END;
  550.  
  551.  
  552.  
  553. PROCEDURE DoKeyDown;
  554. VAR
  555.     MenuChoice:     LongInt;
  556.     temp,
  557.     theMenu,
  558.     theItem:        Integer;
  559.     tempStr:        Str255;
  560. BEGIN
  561.     IF BitAnd(anEvent.modifiers, cmdKey) <> 0 then
  562.     BEGIN
  563.         MenuChoice := MenuKey( CHR( LoWord(anEvent.message)));
  564.         if MenuChoice <> 0 then
  565.         BEGIN
  566.             theMenu := HiWord(MenuChoice);
  567.             theItem := LoWord(MenuChoice);
  568.             CASE theMenu OF
  569.                 AppleID:    IF theItem = 1 then
  570.                                 BEGIN
  571.                                     DoAbout;
  572.                                 END
  573.                             ELSE
  574.                                 BEGIN
  575.                                     EnableItem(EditMenu, 0);
  576.                                     EnableItem(EditMenu, 1);
  577.                                     EnableItem(EditMenu, 3);
  578.                                     EnableItem(EditMenu, 4);
  579.                                     EnableItem(EditMenu, 5);
  580.                                     EnableItem(EditMenu, 6);
  581.                                     DrawMenuBar;
  582.                                     GetItem(AppleMenu, theItem, tempStr);
  583.                                     temp := OpenDeskAcc(tempStr);
  584.                                 END;
  585.                 FileID:     IF theItem = QuitItem then
  586.                                             ProgramDone := true;
  587.                 EditID:     if SystemEdit(theItem - 1) then;
  588.             END;    {case}
  589.             HiliteMenu(0);
  590.         END;    {if MenuChoice...}
  591.     END         {if BitAnd}
  592. END;
  593.  
  594.  
  595.  
  596.  
  597.  
  598. BEGIN       {------------- MAIN PROGRAM LOOP ---------------}
  599.     Init;               {Do all the stuff we don't want to see here}
  600.     ResFork;            {open the Rsrc file}
  601.     GetPic;             {get the 4 fish PICT resources into handles}
  602.     GetMenus;           { "   "  menus}
  603.     hDist := SetHDist;
  604.     vDist := SetVDist;
  605.     SetRect( FishRect, 1, 1, 302, 165);     {So the offscreen bitmaps are
  606.                                                 the right size}
  607.     SetUpBitMaps;
  608.     SetRect( FishRect, -302, 51, -1, 215);
  609.                             {starting fish place =offscreen left}
  610.     DisableItem(EditMenu, 0);
  611.  
  612. {------------ Done getting ready, now Go ----------------------------}
  613.  
  614.     REPEAT
  615.         if GetNextEvent(everyEvent, anEvent) then
  616.         CASE anEvent.what OF
  617.             MouseDown:      DoMouseDown;
  618.             KeyDown,
  619.             autoKey:        DoKeyDown;
  620.             upDateEvt:
  621.                {BeginUpDate(theWindP); }
  622.                 BEGIN
  623.                     TestEdges;
  624.                     DrawTheFish( FishRect);
  625.                     Delay(myDelay, myTicks);     {ticks}
  626.                 END;
  627.                {EndUpDate(theWindP); }
  628.         END;    {case}
  629.         SystemTask;         {make the cursor blink, etc}
  630.         GetMouse(where);
  631.         if FrontWindow = theWindP then
  632.             if where.v < 20 then
  633.             BEGIN
  634.                 InitCursor;     {can't just ShowCursor, since
  635.                                  we don't know how many times we've
  636.                                  done a HideCursor}
  637.             END
  638.             else
  639.                 HideCursor;
  640.     UNTIL ProgramDone;
  641.  
  642.     ReleaseResource( Handle( PicHandle1));
  643.     ReleaseResource( Handle( PicHandle2));
  644.     ReleaseResource( Handle( PicHandle3));
  645.     ReleaseResource( Handle( PicHandle4));
  646.     InitCursor;
  647. END.
  648.